﻿using System;
using System.Threading;
using System.Threading.Tasks;
using BookSleeve;
using RedisDemos.Extensions;

namespace RedisDemos.Scenarios
{
    public class JobQueues : Scenario
    {
        private readonly Int32 timeoutInSecs = 2;
        private readonly Int32 producerIntervalInMillisecs = 250;
        private readonly Int32 delayInSecs = 5;
        private volatile Boolean producerRunning, consumerRunning;

        protected override async Task Perform(RedisConnection conn)
        {
            producerRunning = consumerRunning = true;
            StartConsumerTask(conn);

            await Task.Delay(TimeSpan.FromSeconds(delayInSecs));
            StartProducer(conn);

            await Task.Delay(TimeSpan.FromSeconds(delayInSecs));
            producerRunning = false;

            await Task.Delay(TimeSpan.FromSeconds(delayInSecs));
            consumerRunning = false;
        }

        private void StartProducer(RedisConnection conn)
        {
            var jobDataSource = new Random();
            Task.Factory.StartNew(async () =>
            {
                while (producerRunning)
                {
                    // RPUSH key value [value ...] 
                    await conn.Lists.AddLast(Db, "newsletters:queue", jobDataSource.Next(100).Dump());
                    Thread.Sleep(producerIntervalInMillisecs);
                }
                "Producer stopped, bye bye.".LogInfo();
            }, TaskCreationOptions.LongRunning);
        }

        private void StartConsumerTask(RedisConnection conn)
        {
            Task.Factory.StartNew(async () =>
            {
                while (consumerRunning)
                {
                    // BLPOP key [key ...] timeout 
                    var work = await conn.Lists.BlockingRemoveFirst(Db, new[] { "newsletters:queue" }, timeoutInSecs);
                    "Woke up: {0}".LogInfo(work == null
                            ? " timedout, nothing todo."
                            : " work " + work.Item1 + ":" + work.Item2.AsString());
                }
                "Consumer stopped, bye bye.".LogInfo();
            }, TaskCreationOptions.LongRunning);
        }
    }
}
